package com.lambkit.module.upms.kernel.satoken;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.lambkit.LambkitConsts;
import com.lambkit.auth.AuthUser;
import com.lambkit.auth.exception.IncorrectCredentialsException;
import com.lambkit.auth.exception.LockedAccountException;
import com.lambkit.auth.exception.UnknownAccountException;
import com.lambkit.auth.service.AuthDataService;
import com.lambkit.core.Lambkit;
import com.lambkit.module.upms.Upms;
import com.lambkit.module.upms.UpmsApiService;
import com.lambkit.module.upms.UpmsConsts;
import com.lambkit.module.upms.auth.service.AbstractAuthKernelService;
import com.lambkit.module.upms.auth.service.UpmsDataService;
import com.lambkit.module.upms.row.UpmsUser;

/**
 * @author yangyong(孤竹行)
 */
public class SaTokenKernelService extends AbstractAuthKernelService {
    //loginType = 0-account-password, 1-phone-verifyCode, 99-unpassword无密认证
    @Override
    public String login(AuthUser authUser, String password, int loginType) {
        if (null == authUser || null == authUser.getUserBean()) {
            throw new UnknownAccountException();
        }
        //无密认证
        if (loginType == UpmsConsts.UPMS_LOGIN_TYPE_UNPSWD) {
            return login(authUser);
        }
        // 查询用户信息
        UpmsUser upmsUser = (UpmsUser) authUser.getUserBean();
        if(loginType==1) {
            //phone
            boolean flag = verifySMS(upmsUser.getPhone(), password);
            if(!flag) {
                throw new IncorrectCredentialsException();
            }
        } else {
            //email or username
            if (!upmsUser.getPassword().equals(SecureUtil.md5(password + upmsUser.getSalt()))) {
                throw new IncorrectCredentialsException();
            }
        }
        if (upmsUser.getLocked() == UpmsUser.STATUS_LOCK_ID) {
            throw new LockedAccountException();
        }
        String username = upmsUser.getUsername();
        SaTokenInfo tokenInfo = getToken(username);
        String sessionId = tokenInfo.tokenValue;
        loginSuccess(sessionId, authUser);
        return sessionId;
    }

    private SaTokenInfo getToken(String username) {
        StpUtil.login(username);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }

    /**
     * 验证短信验证码登陆
     * @param phone 手机号
     * @param verifyCode
     * @return
     */
    private boolean verifySMS(String phone, String verifyCode) {
        if(StrUtil.isBlank(verifyCode)) {
            return false;
        }
        // 缓存中验证码
        String cacheVerifyCode = Lambkit.getCache().get(LambkitConsts.SMS_CACHE_PHONE, phone);
        //System.out.println("mobile: " + to + ", code: " + cacheVerifyCode + ", verifyCode: " + verifyCode);
        // 如果赎金来的验证码和缓存中的验证码一致，则验证成功
        if (verifyCode.equals(cacheVerifyCode)) {
            return true;
        }
        return false;
    }

    /**
     * 无密认证
     * @param authUser
     * @return
     */
    @Override
    public String login(AuthUser authUser) {

        if (null == authUser || null == authUser.getUserBean()) {
            throw new UnknownAccountException();
        }
        // 查询用户信息
        UpmsUser upmsUser = (UpmsUser) authUser.getUserBean();
        if (null == upmsUser) {
            throw new UnknownAccountException();
        }
        if(upmsUser.getLocked()==UpmsUser.STATUS_LOCK_ID) {
            throw new LockedAccountException();
        }
        SaTokenInfo tokenInfo = getToken(upmsUser.getUsername());
        String sessionId = tokenInfo.tokenValue;
        loginSuccess(sessionId, authUser);
        return sessionId;
    }

    private void loginSuccess(String sessionId, AuthUser authUser) {
        UpmsDataService dataService = Lambkit.get(UpmsDataService.class);
        dataService.getCache().login(authUser, sessionId);
        //RequestManager.me().setCookie(UpmsConstant.LAMBKIT_UPMS_SERVER_SESSION_ID, sessionId, -1);
    }

    @Override
    public String logout(String sessionIdOrToken) {
        StpUtil.logoutByTokenValue(sessionIdOrToken);
        logoutSuccess(sessionIdOrToken);
        return null;
    }

    private void logoutSuccess(String sessionIdOrToken) {
        AuthDataService dataService = Upms.getAuthDataService();
        dataService.getCache().logout(sessionIdOrToken);
        //RequestManager.me().removeCookie(UpmsConstant.LAMBKIT_UPMS_SERVER_SESSION_ID);
    }

    @Override
    public String authenticate(String sessionIdOrToken) {
        AuthDataService dataService = Upms.getAuthDataService();
        AuthUser authUser = dataService.getCache().validate(sessionIdOrToken);
        if(authUser!=null) {
            String username = authUser.getUserName();
            boolean flag = StpUtil.isLogin(username);
            return flag ? username : null;
        }
        return null;
    }

    @Override
    public AuthUser getAuth(String sessionIdOrToken) {
        AuthDataService dataService = Upms.getAuthDataService();
        AuthUser authUser = dataService.getCache().getAuthUser(sessionIdOrToken);
        if(authUser!=null) {
            String username = authUser.getUserName();
            boolean flag = StpUtil.isLogin(username);
            return flag ? authUser : null;
        }
        return null;
    }
}
